/*
 * @Description:
 * @Version: V1.0
 * @Author: zw_1520@163.com
 * @Date: 2024-09-02 08:42:26
 * @LastEditors: zw_1520@163.com
 * @LastEditTime: 2025-07-02 15:20:37
 * Copyright (C) All rights reserved.
 */

#ifndef __ROBOT_HARDWARE_API_H__
#define __ROBOT_HARDWARE_API_H__
#include <grpcpp/grpcpp.h>

#include <condition_variable>
#include <iostream>
#include <memory>
#include <queue>
#include <rclcpp/rclcpp.hpp>
#include <string>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_cat.h"
#include "robot_grpc_proto/signal.grpc.pb.h"

// ABSL_FLAG(std::string, target, "localhost:50051", "Server address");

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using grpc::StatusCode;

using lensrobot::GeneralMsg;
using lensrobot::Login;
using lensrobot::SignalMsgService;
using lensrobot::StartMedia;

// Requests each key in the vector and displays the key and its corresponding
// value as a pair.

class StreamDataReactor
    : public grpc::ClientBidiReactor<GeneralMsg, GeneralMsg> {
public:
  StreamDataReactor(std::shared_ptr<grpc::Channel> channel)
      : stub_(SignalMsgService::NewStub(channel)) {
    // context_ = std::make_unique<ClientContext>();
    //  stream_ = stub_->RobotControlStream(context_.get(), this);
    stub_->async()->MsgStream(&context_, this);
    StartRead(&response_);
    StartCall();
  }

  void SendData(const GeneralMsg &request);
  void OnWriteDone(bool ok);
  void OnReadDone(bool ok);
  void OnDone(const Status &status);

private:
  std::unique_ptr<SignalMsgService::Stub> stub_;
  ClientContext context_;
  std::unique_ptr<grpc::ClientAsyncReaderWriter<GeneralMsg, GeneralMsg>>
      stream_;
  GeneralMsg request_;
  GeneralMsg response_;
  bool write_in_progress_ = false;
  std::queue<GeneralMsg> request_queue_;
};

class RobotGrpcClient {
public:
  RobotGrpcClient(std::shared_ptr<Channel> channel)
      : reactor_(new StreamDataReactor(channel)) {
    if (!channel) {
      std::cout << "channel is null" << std::endl;
    } else {
      auto state = channel->GetState(true);
      state == GRPC_CHANNEL_READY || state == GRPC_CHANNEL_IDLE;
      std::cout << "channel state: " << state << std::endl;
    }
  }

  void sendData(const GeneralMsg &request);

private:
  StreamDataReactor *reactor_;
};

#endif